'''
Created on 2009-11-9

@author: Madlee
'''
import wx
import wx.xrc  as  xrc
import kuai.kan.resource as rc

BASIC_INPUT_DIALOG_RC = r"""<?xml version="1.0" encoding="UTF-8"?>
<resource>
  <object class="wxDialog" name="BasicInputDialog">
    <object class="wxFlexGridSizer">
      <object class="sizeritem">
        <object class="wxPanel" name="ID_MAIN_PANE"/>
        <flag>wxALL|wxEXPAND</flag>
        <border>5</border>
      </object>
      <object class="sizeritem">
        <object class="wxBoxSizer">
          <object class="sizeritem">
            <object class="wxButton" name="wxID_OK"/>
            <flag>wxLEFT|wxRIGHT</flag>
            <border>5</border>
          </object>
          <object class="sizeritem">
            <object class="wxButton" name="wxID_CANCEL"/>
            <flag>wxLEFT|wxRIGHT</flag>
            <border>5</border>
          </object>
          <orient>wxHORIZONTAL</orient>
        </object>
        <flag>wxBOTTOM|wxALIGN_CENTRE</flag>
        <border>5</border>
      </object>
      <cols>1</cols>
      <rows>2</rows>
      <vgap>5</vgap>
      <hgap>5</hgap>
      <growablecols>0</growablecols>
      <growablerows>0</growablerows>
    </object>
    <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
  </object>
</resource>
"""


def get_frame(component):
    while component is not None:
        if isinstance(component, wx.Frame) or isinstance(component, wx.Dialog):
            break
        else:
            component = component.GetParent()
    return component

def show_error(err, parent=None):
    parent = get_frame(parent)
    return wx.MessageBox(str(err), rc.S_ERROR_CAPTION, wx.OK | wx.ICON_ERROR, parent);

def init_panel(self, parent, rcid, default, *args, **kwargs):
    try:
        res = wx.GetApp().res
    except:
        res = xrc.EmptyXmlResource()
        res.LoadFromString(default)
    pre = wx.PrePanel()
    res.LoadOnPanel(pre, parent, rcid)
    self.PostCreate(pre)
    BasicInputInterface.__init__(self, parent, *args, **kwargs)

class BasicInputDialog(wx.Dialog):
    def __init__(self, owner):
        try:
            res = wx.GetApp().res
        except:
            res = xrc.EmptyXmlResource()
            res.LoadFromString(BASIC_INPUT_DIALOG_RC)
        pre = wx.PreDialog()
        res.LoadOnDialog(pre, owner, "BasicInputDialog")
        self.PostCreate(pre)
        
def show_in_dialog(panel, title, owner, pref=None, *args, **kwargs):
    owner = get_frame(owner)
    dlg = BasicInputDialog(owner)
     
    dlg.SetTitle(title)
    pane = dlg.GetChildren()[0]
    box = wx.BoxSizer(wx.HORIZONTAL)
    pane.SetSizer(box)
    panel = panel(pane, *args, **kwargs)
    data = panel.load_pref({}, pref)
    panel.setup(data)
    box.Add(panel, 1, wx.EXPAND)
    pane.Fit()
    dlg.Fit()
    result = dlg.ShowModal()
    return panel, result
  

def show_input_dialog(panel, title, owner, pref=None, *args, **kwargs):
    panel, result = show_in_dialog(panel, title, owner, *args, **kwargs)
    if result == wx.ID_OK:
        return panel.collect({})
    else:
        return None

def show_and_run(panel, title, owner=None, pref=None, *args, **kwargs):
    panel, result = show_in_dialog(panel, title, owner, *args, **kwargs)
    if result == wx.ID_OK:
        data = panel.collect({})
        if pref:
            panel.save_pref(pref, data)
        return panel.execute(data)
    else:
        return None
    
def show_panel_in_main(panel, title, pref, *args, **kwargs):
    app = wx.PySimpleApp()
    return show_and_run(panel, title, None, pref, *args, **kwargs)

class BasicInputInterface:
    def __init__(self, *args, **kwargs):
        pass
    
    def setup(self, data):
        pass
        
    def collect(self, data):
        """This function try to check and collect all input data. If the input data has
some problem, it throws an exception to tell the caller. And if the input is OK,
it return all data in a dictionary.
@param data: The default data. It is suggested that save the modified data into 
this param and return it directly.
@return The collected data
@throws Error Message if the input data is not correct."""
        return data
    
    def load_pref(self, data, pref):
        """This function try to collect the init data from Preferences. If the data is 
not existed in the Preferences, it should return the default settings. All the
default data and collected data should pack into a hash table and return to the
caller. The default function do nothing and return the data directly.
@param data: Default parameters setup by the caller. It should keep 
unchanged if you do not read from pref. And you should assign the 
missing default data if the are not in it.
@param pref: The Preferences to collect input data.
@return The init data"""
        return data
    
    def save_pref(self, pref, data):
        pass
    
    def execute(self, data):
        return data
    
    def check(self):
        self.collect({})
